<template>
    <!-- 搜索 v-permission="props.permission"-->
    <searchVue
        :list="page.search"
        @search="onSearch"
        @reset="onReset"
        ref="searchRef"
        v-if="searchVisible"
        v-permission="props.page.permission"
    >
        <!-- 在搜索后面添加的内容 -->
        <template #add>
            <slot name="add"></slot>
        </template>
        <!-- 通过输入内容获取企业id -->
        <template #custom>
            <searchTrainSiteNameVue
                :data="searchTrainSiteName"
                @change="onSelectCompanyId"
                :placeholder="placeholderText"
            ></searchTrainSiteNameVue>
        </template>
    </searchVue>
    <div class="table-container">
        <!-- 搜索与表格之间的按钮 -->
        <div :class="['slot', page.headerOperation.length ? 'insert' : '']" ref="insertRef">
            <template v-for="item in page.headerOperation" :key="item.type">
                <section
                    v-if="item.button === 'button'"
                    :class="['button', 'border', item.buttonType]"
                    @click="emits('operation', { type: item.type, data: null })"
                    v-permission="item.permission"
                >
                    {{ item.name }}
                </section>
                <section
                    v-else-if="item.button === 'file'"
                    :class="['button', 'border', 'file', item.buttonType]"
                    v-permission="item.permission"
                >
                    <input
                        type="file"
                        @change="
                            (res: any) => {
                                console.log(res)
                                emits('operation', { type: item.type, data: res.target.files })
                            }
                        "
                    />{{ item.name }}
                </section>
                <el-radio-group
                    v-else-if="item.button === 'radio-button'"
                    v-model="item.modelValue"
                    @change="
                        (res: any) => {
                            item.modelValue = res
                            emits('operation', { type: item.key, data: res })
                        }
                    "
                >
                    <el-radio-button v-for="child in item.radioGroup" :key="child" :label="child" />
                </el-radio-group>
            </template>
        </div>
        <!-- 表格 -->

        <div
            :class="['table', page.headerOperation.length ? 'insert' : '', page.table.isDialog ? 'dialog' : '']"
            ref="tableRef"
            :style="{
                maxHeight: page.headerOperation.length
                    ? `calc(100% - ${searchHeight}px - 32px - 64px)`
                    : `calc(100% - ${searchHeight}px - 32px - 16px)`
            }"
        >
            <el-table
                ref="multipleTableRef"
                :data="page.table.data"
                style="width: 100%; height: 100%; max-height: 100%"
                :border="false"
                @selection-change="handleSelectionChange"
                :header-cell-style="{ background: '#F5F5F5' }"
                :summary-method="getSummaries"
                :show-summary="page.table.showSummary"
                :row-style="{}"
            >
                <!-- 选择框 -->
                <el-table-column fixed type="selection" width="40" v-if="page.table.selection"></el-table-column>
                <!-- 扩展框 -->
                <el-table-column fixed type="expand" width="40" v-if="page.table.expand">
                    <template #default="scope">
                        <slot name="expand">
                            <div class="expand-container">
                                <div class="line" v-for="(item, key) in page.table.expandKey" :key="item">
                                    <p>{{ item }}：</p>
                                    <span v-if="DICT_DATA.has(key + '')">
                                        <template v-if="scope.row[key] !== '' && scope.row[key] !== null">
                                            <DictVue
                                                :data="DICT_DATA.get(key + '')"
                                                :value="val"
                                                v-for="(val, index) in scope.row[key].toString().split(',')"
                                                :key="val"
                                                :style="{
                                                    'margin-right':
                                                        index < scope.row[key].toString().split(',').length ? '8px' : 0
                                                }"
                                            ></DictVue>
                                        </template>
                                    </span>
                                    <span v-else>{{ scope.row[key] }}</span>
                                </div>
                            </div>
                        </slot>
                    </template>
                </el-table-column>
                <!-- 序号 -->
                <el-table-column fixed type="index" width="54" v-if="page.table.index" label="序号" align="center" />
                <template v-for="(item, index) in defaultProperty" :key="item">
                    <!-- 操作按钮 -->
                    <el-table-column
                        fixed="right"
                        v-if="item.operation.length"
                        :label="item.label"
                        :width="item.width"
                        align="center"
                    >
                        <template #header>
                            <div class="operation-header">
                                <h1>操作</h1>
                                <h2>
                                    <el-popover placement="top-end" width="50%" trigger="click" @show="onPopoverShow">
                                        <template #reference>
                                            <el-icon><SetUp /></el-icon>
                                        </template>
                                        <div class="pull-down-box">
                                            <div style="margin-bottom: 8px">
                                                <p style="display: flex; align-items: center">
                                                    选择显示的列
                                                    <el-tooltip
                                                        class="box-item"
                                                        effect="dark"
                                                        content="长按选项可拖动，改变列的位置"
                                                        placement="top"
                                                    >
                                                        <el-icon><QuestionFilled /></el-icon>
                                                    </el-tooltip>
                                                    <el-button
                                                        style="margin-left: 8px"
                                                        size="small"
                                                        @click="onResetProperty"
                                                        >重置</el-button
                                                    >
                                                </p>
                                            </div>
                                            <el-checkbox-group
                                                v-model="selectProperty.list"
                                                @change="handleCheckedChange"
                                                id="checkbox-group"
                                            >
                                                <template v-for="p in originalProperty" :key="p.prop">
                                                    <el-checkbox :label="p.prop" v-if="p.prop !== 'operate'">{{
                                                        p.label
                                                    }}</el-checkbox>
                                                </template>
                                            </el-checkbox-group>
                                        </div>
                                    </el-popover>
                                </h2>
                            </div>
                        </template>
                        <template #default="scope">
                            <!-- v-permission="opera.permission" -->
                            <div class="operation">
                                <div v-for="opera in item.operation" :key="opera.type">
                                    <span
                                        :class="['custom-button', opera.className]"
                                        v-if="setVisible(opera.visible as visibleType, scope.row)"
                                        @click="emits('operation', { type: opera.type, data: scope.row })"
                                        v-permission="opera.permission"
                                        >{{ opera.name }}</span
                                    >
                                </div>
                            </div>
                        </template>
                    </el-table-column>
                    <!-- 滑块 开关按钮 -->
                    <el-table-column v-else-if="item.switch" :label="item.label" align="center" width="90px">
                        <template #default="scope">
                            <template v-if="page.table.switch.tooltip.visible">
                                <!-- 鼠标移到开关按钮上显示有提示 -->
                                <el-tooltip :content="page.table.switch.tooltip.content" :disabled="!scope.row.status">
                                    <el-switch
                                        v-permission="page.table.switch.permission"
                                        v-model="scope.row.status"
                                        inline-prompt
                                        active-text="启用"
                                        inactive-text="禁用"
                                        style="height: 24px"
                                        @change="emits('operation', { type: 'switch', data: scope.row })"
                                    />
                                </el-tooltip>
                            </template>
                            <template v-else>
                                <el-switch
                                    v-permission="page.table.switch.permission"
                                    v-model="scope.row.status"
                                    inline-prompt
                                    active-text="启用"
                                    inactive-text="禁用"
                                    style="height: 24px"
                                    @change="emits('operation', { type: 'switch', data: scope.row })"
                                />
                            </template>
                        </template>
                    </el-table-column>
                    <!-- 判断是否存在某个字典 -->
                    <el-table-column
                        v-else-if="DICT_DATA.has(item.prop)"
                        :label="item.label"
                        :sortable="page.table.sortable.includes(item.prop)"
                        :prop="item.prop"
                        :show-overflow-tooltip="true"
                        align="center"
                        :width="item.width || '100px'"
                        min-width="100px"
                    >
                        <template #default="scope">
                            <template v-if="scope.row[item.prop] !== '' && scope.row[item.prop] !== null">
                                <DictVue
                                    :data="DICT_DATA.get(item.prop)"
                                    :value="val"
                                    v-for="(val, index) in scope.row[item.prop].toString().split(',')"
                                    :key="val"
                                    :style="{
                                        'margin-right':
                                            index < scope.row[item.prop].toString().split(',').length ? '8px' : 0
                                    }"
                                ></DictVue>
                            </template>
                        </template>
                    </el-table-column>
                    <!-- 多级表头 -->
                    <el-table-column v-else-if="item.children.length" :label="item.label" align="center">
                        <el-table-column
                            :label="child.label"
                            v-for="(child, index) in item.children"
                            :prop="child.prop"
                            :key="child"
                            align="center"
                        >
                        </el-table-column>
                    </el-table-column>
                    <!-- 图片 -->
                    <el-table-column v-else-if="item.prop === 'imageUrl'" :label="item.label" align="center">
                        <template #default="scope">
                            <el-image
                                style="width: 50px; height: 40px"
                                :src="scope.row[item.prop]"
                                :zoom-rate="1.2"
                                :max-scale="7"
                                :min-scale="0.2"
                                :preview-src-list="[scope.row[item.prop]]"
                                :initial-index="4"
                                :preview-teleported="true"
                                :lazy="true"
                                fit="cover"
                            />
                        </template>
                    </el-table-column>
                    <!-- 颜色 -->
                    <el-table-column v-else-if="item.prop === 'color'" :label="item.label" align="center" width="120">
                        <template #default="scope">
                            <div style="display: flex">
                                <span
                                    :style="{
                                        'background-color': scope.row[item.prop],
                                        display: 'block',
                                        width: '24px',
                                        height: '24px',
                                        'border-radius': '4px',
                                        'margin-right': '8px'
                                    }"
                                ></span>
                                <span>{{ scope.row[item.prop] }}</span>
                            </div>
                        </template>
                    </el-table-column>
                    <!-- 默认情况 -->
                    <!-- width 根据表格的属性进行区分设置宽度 -->
                    <el-table-column
                        v-else
                        :prop="item.prop"
                        :label="item.label"
                        :sortable="page.table.sortable.includes(item.prop)"
                        :show-overflow-tooltip="true"
                        align="center"
                        :width="item.width"
                        min-width="100px"
                        :fixed="page.table.fixed.includes(item.prop)"
                    ></el-table-column>
                </template>
            </el-table>
        </div>
    </div>
    <!-- 分页 -->
    <paginationVue :pagination="page.pagination" @change="onPaginationChange" @page-size="onPaginationSize" />
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watchEffect, reactive, watch } from 'vue'
import searchVue from '../search/Index.vue'
import paginationVue from '../Pagination.vue'
import DictVue from '../dict/Index.vue'
import { DICT_DATA } from '@/utils/dict-data'
import { ElTable } from 'element-plus'
import type { TableColumnCtx } from 'element-plus'
import searchTrainSiteNameVue from '@/components/searchTrainSiteName.vue'
import { visibleType, pageDataInterface } from '@/utils/basc-data'
import { summaryMap, setVisible } from './tableSet'
import { useRoute } from 'vue-router'
import { storage } from '@/store/sessionStorage'
import Sortable from 'sortablejs'

const route = useRoute()

/**
 * 监听table高度
 */
const tableRef = ref(0)

/**
 * 监听搜索栏高度
 */
const searchRef = ref()

/**
 * 设置搜索栏高度
 */
const searchHeight = ref(50)

/**
 * 设置搜索栏是否显示 根据传递的list参数是否为空判断
 */
const searchVisible = ref(true)

//监听是否有插入的内容
const insertRef = ref()
const insert = ref(false)

//搜索企业id输入提示
const placeholderText = ref('')
// const issearchTrainSiteName = ref(false)
const searchTrainSiteName = reactive({
    width: '100%',
    name: '',
    disabled: false
})
const companyId = ref('')
/**
 * 监听检索选择的公司id
 * @param id
 */
const onSelectCompanyId = (res: any) => {
    console.log('companyId', res)
    companyId.value = res.value
    searchTrainSiteName.name = res.name
}

/**
 * 接收父组件传递的参数
 */
const props = defineProps({
    page: {
        type: Object,
        default: () => {
            return {
                headerOperation: [],
                permission: [],
                pagination: {
                    pageNo: 1,
                    pageSize: 20,
                    total: 0
                },
                table: {
                    data: [],
                    describe: [],
                    selection: false,
                    expand: false,
                    index: true,
                    list: [],
                    showSummary: false,
                    summaryArray: [],
                    summaryType: '',
                    sortable: [],
                    isDialog: false,
                    switch: {
                        disabled: false,
                        permission: [],
                        tooltip: {
                            visible: false,
                            content: ''
                        }
                    }
                },
                search: []
            }
        }
    }
})

/**
 * 注册父组件的回调
 */
const emits = defineEmits(['search', 'reset', 'paginationChange', 'paginationSize', 'multiSelection', 'operation'])

//选择表格默认显示的字段
const defaultProperty: any[] = reactive([])
const selectProperty: { list: string[] } = reactive({
    list: []
})
//初始化表格显示的属性
const originalProperty: any[] = reactive([])

//创建map保存用户勾选显示的列
const propertyMap = new Map<string, any>()

//创建map保存表格默认排序的列
const defaultSortMap = new Map<string, any>()

//监听选择显示属性的变化
const handleCheckedChange = (list: any[]) => {
    setSelectProperty(list)

    propertyMap.set(route.fullPath, list)
    localStorage.setItem('propertyMap', JSON.stringify(Object.fromEntries(propertyMap)))
}
//监听拖动显示的列
const onPopoverShow = () => {
    const el = document.querySelector('#checkbox-group') as HTMLElement

    Sortable.create(el, {
        animation: 150,
        ghostClass: 'blue-background-class',
        onEnd: (/**Event*/ evt: any) => {
            const { oldIndex, newIndex } = evt
            let el = originalProperty.splice(oldIndex, 1)[0]
            originalProperty.splice(newIndex, 0, el)

            //根据排序重新更新表格排列顺序
            const list: string[] = []
            defaultProperty.length = 0
            selectProperty.list.forEach(str => {})
            originalProperty.forEach((item: any, index: number) => {
                if (selectProperty.list.includes(item.prop)) {
                    list.push(item.prop)
                }
            })

            setSelectProperty(list)

            //保存返回的key
            defaultSortMap.set(
                route.fullPath,
                originalProperty.map((item: any) => item.prop)
            )
            localStorage.setItem('defaultSortMap', JSON.stringify(Object.fromEntries(defaultSortMap)))
        }
    })
}

//重置显示属性
const onResetProperty = () => {
    defaultProperty.length = 0
    selectProperty.list.length = 0
    originalProperty.length = 0

    propertyMap.delete(route.fullPath)
    localStorage.setItem('propertyMap', JSON.stringify(Object.fromEntries(propertyMap)))
    defaultSortMap.delete(route.fullPath)
    localStorage.setItem('defaultSortMap', JSON.stringify(Object.fromEntries(defaultSortMap)))

    props.page.table.describe.forEach((item: any) => {
        console.log('item', item)
        defaultProperty.push(item)
        selectProperty.list.push(item.prop)
        originalProperty.push(item)
    })
}

/**
 * 监听点击搜索按钮
 * @param res
 */
const onSearch = (res: any) => {
    if ('custom' in res) {
        res['companyId'] = companyId.value
        res['custom'] = { companyId: companyId.value, companyName: searchTrainSiteName.name }
    }

    emits('search', res)
}

/**
 * 监听点击重置按钮
 */
const onReset = () => {
    searchTrainSiteName.name = ''
    companyId.value = ''
    emits('reset')
}

/**
 * 监听选择的当前分页
 * @param index
 */
const onPaginationChange = (index: number) => {
    emits('paginationChange', index)
}

/**
 * 监听分页大小的改变
 * @param index
 */
const onPaginationSize = (index: number) => {
    emits('paginationSize', index)
}

const multipleTableRef = ref<InstanceType<typeof ElTable>>()

/**
 * 表格全选框回调
 * @param res
 */
const handleSelectionChange = (rows: any[]) => {
    emits('multiSelection', rows)
}

/**
 * 获取搜索栏的高度
 */
const getSearchHeight = () => {
    searchHeight.value = searchVisible.value === true ? searchRef.value.$el.clientHeight : 0
    // console.log('insertRef', insertRef)
    insert.value = insertRef.value.children.length ? true : false
}

/**
 * 页面初次挂载完成
 */
onMounted(() => {
    getSearchHeight()
    window.addEventListener<'resize'>('resize', getSearchHeight)
})

/**
 * 页面卸载之前
 */
onBeforeUnmount(() => {
    window.removeEventListener<'resize'>('resize', getSearchHeight)
})

/**
 * 监听 props 参数变化
 */

watchEffect(() => {
    searchVisible.value = props.page.search.length ? true : false
    if (searchVisible.value) {
        props.page.search.forEach((item: any) => {
            if (Object.prototype.toString.call(item) === '[object Array]') {
                placeholderText.value = item.length > 1 ? item[1] : '请输入公司名称|编号'
            }
        })
    }
})

watch(props.page, (newVal: any, old: any) => {
    //从本地缓存获取默认排序的列
    originalProperty.length = 0
    const describeArr: any = JSON.parse(JSON.stringify(newVal.table.describe))

    const sortStr = localStorage.getItem('defaultSortMap')
    if (sortStr && sortStr !== null) {
        const obj = JSON.parse(sortStr)
        for (const key in obj) {
            defaultSortMap.set(key, obj[key])
        }
        if (defaultSortMap.has(route.fullPath)) {
            const list: any[] = defaultSortMap.get(route.fullPath)
            const sortMap = list.reduce((acc, prop, index) => {
                acc[prop] = index
                return acc
            }, {})

            describeArr.sort((a: any, b: any) => sortMap[a.prop] - sortMap[b.prop])
            originalProperty.push(...describeArr)
        } else {
            originalProperty.push(...describeArr)
        }
    } else {
        originalProperty.push(...describeArr)
    }

    //首先从本地缓存中获取用户勾选显示的列
    // propertyMap.has
    const str = localStorage.getItem('propertyMap')

    if (str && str !== null) {
        const obj = JSON.parse(str)
        for (const key in obj) {
            propertyMap.set(key, obj[key])
        }
        if (propertyMap.has(route.fullPath)) {
            selectProperty.list.length = 0
            const list = propertyMap.get(route.fullPath)
            selectProperty.list.push(...list)

            setSelectProperty(list)
        } else {
            initProperty(setDefaultNotSelectProperty(originalProperty))
        }
    } else {
        initProperty(setDefaultNotSelectProperty(originalProperty))
    }
})

//默认不勾选【所在区域】和【分销人员】
function setDefaultNotSelectProperty(list: any[]) {
    const arr: any[] = []
    list.forEach((item: any) => {
        if (item.prop !== 'area' && item.prop !== 'referrerStr') {
            arr.push(item)
        }
    })
    return arr
}
//设置初始化默认属性
function initProperty(list: any[]) {
    selectProperty.list.length = 0
    defaultProperty.length = 0
    list.forEach((item: any) => {
        defaultProperty.push(item)
        if (item.propName !== 'operate') {
            selectProperty.list.push(item.prop)
        }
    })
}
//设置筛选属性
function setSelectProperty(list: any[]) {
    defaultProperty.length = 0
    //记录哪个列的位置
    const sortNum: number[] = []
    list.forEach((item: any) => {
        originalProperty.forEach((child: any, index: number) => {
            if (child.prop === item) {
                sortNum.push(index)
            }
        })
    })
    //从小到大排列
    sortNum.sort((a, b) => {
        return a - b
    })
    sortNum.forEach(item => {
        defaultProperty.push(originalProperty[item])
    })
}

interface SummaryMethodProps<T = any> {
    columns: TableColumnCtx<T>[]
    data: T[]
}

//设置统计尾行
const getSummaries = (param: SummaryMethodProps) => {
    const { columns, data } = param
    const sums: string[] = []
    columns.forEach((column, index) => {
        sums[index] = props.page.table.summaryArray[index]
    })

    const tds = props.page.table.isDialog
        ? document.querySelectorAll('.el-dialog .el-table__footer-wrapper tr>td')
        : document.querySelectorAll('.table .el-table__footer-wrapper tr>td')
    if (tds.length) {
        console.log('rops.table.summaryType', props.page.table.summaryType)
        summaryMap.get(props.page.table.summaryType)(tds)
    }
    return sums
}
</script>
<style scoped lang="scss">
.operation-header {
    display: flex;
    align-items: center;
    justify-content: center;
    h1 {
        font-size: 14px;
        font-weight: bold;
        line-height: 24px;
    }
    h2 {
        font-size: 14px;
        line-height: 24px;
        width: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-left: 4px;
        cursor: pointer;
    }
}
.operation {
    display: flex;
    div {
        &:first-child {
            margin-left: 12px;
        }
    }
}
.table-container {
    box-sizing: border-box;
    padding: 0;
    background-color: #fff;
    // margin-top: 8px;
}
.table {
    overflow-y: auto;
    &.insert {
        height: auto;
    }
}
.slot.insert {
    margin: 0 0 16px 0;
    display: flex;
    align-items: center;
    .button {
        margin-right: 16px;
    }
}
.expand-container {
    box-sizing: border-box;
    padding: 16px;
    display: flex;
    flex-wrap: wrap;

    .line {
        width: 50%;
        display: block;
        display: flex;
        align-items: center;
        line-height: 32px;
        p {
            width: 100px;
            min-width: 100px;
            text-align: right;
            margin-right: 10px;
        }
    }
}

.swich-box {
    width: 48px;
    height: 20px;
    background-color: #409eff;
    border-radius: 10px;
    overflow: hidden;
    position: relative;
    cursor: pointer;
    transition: all 0.2s;
    &.active {
        background-color: #dcdfe6;
        p {
            text-align: left;
        }
        span {
            left: calc(100% - 2px - 16px);
        }
    }
    p {
        font-size: 12px;
        box-sizing: border-box;
        line-height: 20px;
        color: #fff;
        padding: 0 4px;
        display: block;
        width: 100%;
        text-align: right;
        transition: all 0.2s;
    }
    span {
        transition: all 0.2s;
        display: block;
        width: 16px;
        height: 16px;
        background-color: #fff;
        border-radius: 50%;
        position: absolute;
        top: 2px;
        left: 2px;
    }
}
</style>
